/*
* File:   iohandle.h
* Author: aple
*
* Created on 2014年9月15日, 下午8:29
*/

#ifndef IO_HANDLE_H_
#define IO_HANDLE_H_

#ifdef    __cplusplus
extern "C" {
#endif

#include "stdint.h"

	uint8_t ad_io_creat(uint8_t sample_old, uint16_t ad_true, uint16_t ad_false, uint16_t ad_now);

	typedef struct
	{
		void(*en)(void);
		void(*dis)(void);
		void(*tog)(void);
		uint8_t(*out_st)(void);
	} out_obj_type;

/*****************************************************************************
* @brief	列表处理机中的边沿以当前最大组合数值作为边沿键值处理
* @brief	例如 key1,key2同时按下，调用用 key1|key2组合键的按下沿，
			所有键均弹起后，调用key1|key2组合键弹起沿。
			内部处理顺序按照结构体书写顺序执行
			列表尾部必须为一个键值为0的元素
*****************************************************************************/
	typedef struct 
	{
		// 功能键值-所有操作以最大组合键值处理
		uint32_t key_val;
		// 按下
		void (*press_down)(void);
		// 保持
		void (*press_keep)(void);
		// 弹起
		void (*press_release)(void);
	} key_opt_type;

	typedef struct
	{
		// 任意键按下处理-实时边沿
		void (*key_down_any)(void);
		
		// 任意键保持处理-实时键值
		void (*key_keep_any)(void);
		
		// 键操作列表 - 列表接口以最大组合数为准
		const key_opt_type *key_obj;
		
		// 任意键弹起处理-实时边沿
		void (*key_release_any)(void);
		
		// 空闲处理
		void (*key_idle)(void);
	} key_api_type;
	
	/*key handle*/
	typedef struct
	{
		uint8_t read_flt_cnt;		// 采样滤波计数
		uint8_t b_first_key;		// 首个按键-仅空闲变有键时
		uint8_t b_do_none_rls;		// 按键释放无操作，由应用程序置位
		uint16_t found_time_cnt;	// 按键存在时间
		uint16_t lost_time_cnt;		// 按键空闲时间
		uint16_t keep_time_cnt;		// 键值保持时间
		uint32_t val;				// 键值
		uint32_t old;
		uint32_t mixed_val;			// 最大组合记录， val 和 edge 均为0时自动清除
		uint32_t edge;				// 边沿
		uint32_t found_edge;		// 按下边沿
		uint32_t lost_edge;			// 弹起边沿
		uint32_t read;
		uint32_t read_old;
		const key_api_type *api;
	} key_type;
	void key_st_handle(key_type *key, uint8_t time_pulse);
	void key_st_sample(key_type *key, uint8_t flt_sv, uint32_t key_read);
#define key_st_isr   key_st_sample

	typedef struct
	{
		uint8_t space_sv;   //Y连击有效间隔
		uint8_t serial_sv;  //Y连击次数

		uint8_t space_cnt;
		uint8_t serial_cnt;
		uint8_t key_old;
		uint8_t multi_click_out; //连击输出
		uint8_t edge_found;      //按下边沿
		uint8_t edge_lost;       //弹起边沿
		uint16_t st_keep_cnt;
	} key_click_type;

	uint8_t key_click_handle(key_click_type *obj, uint8_t key_now, uint8_t pulse);

	/*io st*/
	typedef struct
	{
		uint8_t  time_pulse;   //Y--计时脉冲
		uint8_t  sample_pulse; //Y--采样脉冲    
		uint8_t  val;
		uint8_t  old;
		uint8_t found_edge;
		uint8_t lost_edge;
		uint8_t sample_old;
		uint8_t sample_keep_cnt;//0-UINT8_MAX
		uint32_t found_time_cnt;//0-UINT32_MAX
		uint32_t lost_time_cnt; //0-UINT32_MAX
	} in_switch_st_type;

	typedef struct
	{
		struct
		{
			uint8_t  time_pulse : 1;  //计时脉冲
			uint8_t  sample_pulse : 1; //采样脉冲    
			uint8_t  val : 1;
			uint8_t  old : 1;
			uint8_t found_edge : 1;
			uint8_t lost_edge : 1;
			uint8_t sample_old : 1;
		} st;
		uint8_t sample_keep_cnt;//0-UINT8_MAX
		uint16_t found_time_cnt;//0-UINT16_MAX
		uint16_t lost_time_cnt;//0-UINT16_MAX
	} simp_switch_st_type;  //采用位态（节省内存，效率略降），最大计时缩短，功能同in_switch_st_type

	typedef struct
	{
		uint8_t  time_pulse;  //计时脉冲 
		uint8_t  old;
		uint8_t enable_edge;
		uint8_t disable_edge;
		uint32_t enable_time_cnt;//0-UINT32_MAX
		uint32_t disable_time_cnt;//0-UINT32_MAX
	} out_st_type;

	typedef struct
	{
		uint8_t  out;  //计时脉冲 
		uint8_t  old;
		uint8_t enable_edge;
		uint8_t disable_edge;
		uint32_t enable_time_cnt;//0-UINT32_MAX
		uint32_t disable_time_cnt;//0-UINT32_MAX
	} out_stv2_type;

	typedef struct
	{
		struct
		{
			uint8_t  time_pulse : 1;  //计时脉冲 
			uint8_t  old : 1;
			uint8_t enable_edge : 1;
			uint8_t disable_edge : 1;
		} st;
		uint16_t enable_time_cnt;//0-UINT16_MAX
		uint16_t disable_time_cnt;//0-UINT16_MAX
	} simp_out_st_type;

	void in_switch_handle(in_switch_st_type *swobj, uint8_t sw_now);  //内部滤波次数固定值6，输入可以是0和任意非零状态
	void simp_switch_handle(simp_switch_st_type *swobj, uint8_t sw_now);  //内部滤波次数固定值6，输入必须是0和1两个状态
	void out_st_handle(out_st_type *obj, uint8_t out_now);//允许多任务使用
	void out_stv2_handle(out_stv2_type *obj, uint8_t time_pulse);//允许多任务使用
	void simp_out_st_handle(simp_out_st_type *obj, uint8_t out_now); //不可在多任务中使用

	/*--------------------------------------------------------------------------------------------------------------------------*/
	/*rot st*/
	typedef struct
	{
		uint8_t a_st;
		uint8_t a_old;
		uint8_t b_st;
		uint8_t b_old;
		uint8_t b_clock;
		uint8_t b_unti_clock;
		uint16_t clock_none_time_cnt; //间隔计时器，每次调用递增，检测到任意有效旋转，记录该值到 clock_interval
		uint16_t clock_interval;      //间隔
	} rot_key_type;

	void rot_key_handle(rot_key_type *key, uint8_t a, uint8_t b);

	/*--------------------------------------------------------------------------------------------------------------------------*/
	typedef struct
	{
		uint8_t st;     //当前有效状态
		int8_t flt_cnt; //滤波计数，负方向为无效状态，正方向为有效状态，回差带内保持(包含边界)
	} io_flt_type;

	typedef struct
	{
		struct
		{
			uint8_t val : 1;     //当前有效状态
			uint8_t old : 1;
			uint8_t edge : 1;
			uint8_t edge_found : 1;
			uint8_t edge_lost : 1;
		} st;

		int8_t flt_cnt; //滤波计数，负方向为无效状态，正方向为有效状态，回差带内保持(包含边界)
	} io_flt_edge_type;

	typedef struct
	{
		struct
		{
			uint8_t val : 1;     //当前有效状态
			uint8_t old : 1;
			uint8_t edge : 1;
			uint8_t edge_found : 1;
			uint8_t edge_lost : 1;
			uint8_t pulse_sample : 1; //采样脉冲
			uint8_t pulse_time : 1; //计时脉冲
		} st;

		int8_t flt_cnt; //滤波计数，负方向为无效状态，正方向为有效状态，回差带内保持(包含边界)
		uint16_t found_time_cnt;
		uint16_t lost_time_cnt;
	} io_flt_ext_type;

	typedef struct
	{
		struct
		{
			uint8_t val : 1;     //当前有效状态
			uint8_t old : 1;
			uint8_t edge : 1;
			uint8_t edge_found : 1;
			uint8_t edge_lost : 1;
		} st;

		int8_t flt_cnt; //滤波计数，负方向为无效状态，正方向为有效状态，回差带内保持(包含边界)
		uint16_t found_time_cnt;
		uint16_t lost_time_cnt;
	} io_flt_extv2_type;

	typedef struct
	{
		struct
		{
			uint8_t val : 1;     //当前有效状态
			uint8_t old : 1;
			uint8_t edge : 1;
			uint8_t edge_found : 1;
			uint8_t edge_lost : 1;
		} st;
		uint8_t lost_keep_sv, found_keep_sv;  //cnt达到指定sv数，flt_cnt计数一次，0和1均为1次
		uint8_t lost_keep_cnt, found_keep_cnt;
		int8_t flt_cnt; //滤波计数，负方向为无效状态，正方向为有效状态，回差带内保持(包含边界)
		uint16_t found_time_cnt;
		uint16_t lost_time_cnt;
	} io_flt_extv3_type;

	uint8_t io_flt(io_flt_type *io_obj, int8_t flt_sv, uint8_t st_now); //flt_sv 滤波设定，回差带为 (-sv~sv)  ,输出状态改变需要1+2*sv个持续输入
	uint8_t io_flt_edge(io_flt_edge_type *io_obj, uint8_t flt_pulse, int8_t flt_sv, uint8_t st_now);
	uint8_t io_flt_ext(io_flt_ext_type *io_obj, int8_t flt_sv, uint8_t st_now); //flt_sv 滤波设定，回差带为 (-sv~sv)  ,输出状态改变需要1+2*sv个持续输入
	uint8_t io_flt_extv2(io_flt_extv2_type *io_obj, uint8_t flt_pulse, uint8_t time_pulse, int8_t flt_sv, uint8_t st_now);//对称回差滤波
	uint8_t io_flt_extv3(io_flt_extv3_type *io_obj, uint8_t flt_pulse, uint8_t time_pulse, int8_t flt_sv, uint8_t st_now);//非对称回差滤波

	/*---io group filter----*/
	typedef struct
	{
		uint8_t val;
		uint8_t val_old;
		uint8_t read_old;
		uint8_t edge;
		uint8_t edge_found;
		uint8_t edge_lost;
		uint8_t flt_cnt;
	} io8_flt_type;

	typedef struct
	{
		uint16_t val;
		uint16_t val_old;
		uint16_t read_old;
		uint16_t edge;
		uint16_t edge_found;
		uint16_t edge_lost;
		uint8_t flt_cnt;
	} io16_flt_type;

	typedef struct
	{
		uint32_t val;
		uint32_t val_old;
		uint32_t read_old;
		uint32_t edge;
		uint32_t edge_found;
		uint32_t edge_lost;
		uint8_t flt_cnt;
	} io32_flt_type;

	void io8_flt(io8_flt_type *io_obj, uint8_t flt_sv, uint8_t read_now, uint8_t pulse);
	void io16_flt(io16_flt_type *io_obj, uint8_t flt_sv, uint16_t read_now, uint8_t pulse);
	void io32_flt(io32_flt_type *io_obj, uint8_t flt_sv, uint32_t read_now, uint8_t pulse);

	/*---io group filter , just value----*/
	typedef struct
	{
		uint8_t val;
		uint8_t read_old;
		uint8_t flt_cnt;
	} io8_simp_flt_type;

	typedef struct
	{
		uint16_t val;
		uint16_t read_old;
		uint8_t flt_cnt;
	} io16_simp_flt_type;

	typedef struct
	{
		uint32_t val;
		uint32_t read_old;
		uint8_t flt_cnt;
	} io32_simp_flt_type;

	void io8_simp_flt(io8_simp_flt_type *io_obj, uint8_t flt_sv, uint8_t read_now);
	void io16_simp_flt(io16_simp_flt_type *io_obj, uint8_t flt_sv, uint16_t read_now);
	void io32_simp_flt(io32_simp_flt_type *io_obj, uint8_t flt_sv, uint32_t read_now);

	typedef struct
	{
		uint8_t val;
		uint8_t val_old;
		uint8_t edge_found;
		uint8_t edge_lost;
		uint8_t read_old[8];
	} io8_sig_flt_type;
	typedef struct
	{
		uint16_t val;
		uint16_t val_old;
		uint16_t edge_found;
		uint16_t edge_lost;
		uint16_t read_old[8];
	} io16_sig_flt_type;
	typedef struct
	{
		uint32_t val;
		uint32_t val_old;
		uint32_t edge_found;
		uint32_t edge_lost;
		uint32_t read_old[8];
	} io32_sig_flt_type;
	void io8_sig_flt(io8_sig_flt_type *io_obj, uint8_t flt_sv, uint8_t read_now, uint8_t pulse);
	void io16_sig_flt(io16_sig_flt_type *io_obj, uint8_t flt_sv, uint16_t read_now, uint8_t pulse);
	void io32_sig_flt(io32_sig_flt_type *io_obj, uint8_t flt_sv, uint32_t read_now, uint8_t pulse);


	/*---signal info creat----*/
	typedef struct
	{
		uint8_t sig_new;	// Y 外部更新
		uint8_t sig;
		uint8_t sig_old;
		uint8_t edge, edge_found, edge_lost;
		uint16_t found_time_cnt;
		uint16_t lost_time_cnt;
	} io_signal_type;
	uint8_t io_signal_info_handle(io_signal_type *io_obj, uint8_t time_pulse);

	/*---不连续输入滤波----*/
	typedef struct
	{
		uint8_t st;          // RO 输出
		int8_t flt_cnt;      // RO
		uint16_t period_cnt; // RO || >=period_sv 时判定并回零
		uint16_t active_cnt; // RO || >=active_sv 时判定为有效周期
		uint8_t st_old;      // RO

		uint16_t period_sv; //Y--检测周期
		uint16_t active_sv; //Y--一个周期内，有效数大于等于该值时判定为有效，否则无效
		int8_t flt_sv;      //Y--回差数 //以period_sv作为一个滤波周期
		uint8_t flt_pulse;  //Y--采样脉冲
		uint8_t time_pulse; //Y--计时脉冲

		uint8_t found_edge, lost_edge; //RO
		uint16_t found_time; //RO
		uint16_t lost_time;  //RO
	} discont_in_flt_type;

	uint8_t discont_in_flt(discont_in_flt_type *obj, uint8_t in_val);

	/*--------------------------------------------------------------------------------------------------------------------------*/
	typedef struct
	{
		uint8_t out;       //RO
		uint8_t en_edge;   //RO
		uint8_t dis_edge;  //RO
		uint8_t en_req;    //Y手动开启请求
		uint8_t dis_req;   //Y手动停止请求
		uint32_t en_time;  //RO //内部计数最大为2^31，溢出归零
		uint32_t dis_time; //RO //内部计数最大为2^31，溢出归零
	} out_sw_type;;
	/* time_sv 设为0不切换该状态,对应req同时失效.设为其他值保持设定数值脉冲数，设定值>2^31时，保持在该状态，除非手动req    */
	/* pulse 为计时脉冲                                           */
	uint8_t out_sw_manage(out_sw_type * out_obj, uint32_t en_time_sv, uint32_t dis_time_sv, uint8_t pulse);

	/*--------------------------------------------------------------------------------------------------------------------------*/
	typedef struct
	{
		uint8_t out;		// X
		uint8_t err;		// X
		uint8_t comp;		// X 完成标志
		uint16_t en_time;	// X 输出计时
		uint16_t dly_time;	// X 延时计时
	} wt_add_type;;

	/* ot_time_sv  为0时无补水功能，强制关闭输出 */
	/* pulse 为计时脉冲                                           */
	uint8_t wt_add_manage(wt_add_type * out_obj, uint8_t wt_st, uint16_t ot_time_sv, uint16_t dly_time_sv, uint8_t pulse);

	/*-------------------------------------------------------------------------------------------------------------------------*/
	typedef struct
	{
		uint8_t out0;		//X
		uint8_t out1;		//X
		uint8_t mode;		//Y 0-关闭，1out0,2-out1, 其他切换
		uint8_t out_sel;	//X
		int32_t out0_en_time;	//X
		int32_t out0_dis_time;	//X
		int32_t out1_en_time;	//X
		int32_t out1_dis_time;	//X
		int32_t delay_cnt;		//X
		int32_t dev_off_min_time;  //Y 设备最小停机时间
	} dev_double_sw_type;;

	/*****************************************************************************-/
	* @brief   Double cool time handle.
	*          switch_time 必须大于 switch_time_befor+mintime，否则将强制switch_time = switch_time_befor+mintime
	* @param   dev： obj
	* @param   switch_time_set : switch time
	* @param   switch_time_befor : 正数 before-time, 负数delay-time
	* @param   pulse : 计时脉冲
	*****************************************************************************/
	void dev_double_sw(dev_double_sw_type * dev, int32_t switch_time_set, int32_t switch_time_befor, uint8_t pulse);

	/*----正反转控制----*/
	typedef struct
	{
		uint8_t st;			// X 输出状态
		uint8_t st_start;	// Y 起始状态
		uint32_t cct_set;	// Y 正转时间
		uint32_t nct_set;	// Y 反转时间
		uint32_t sot_set;	// Y 停止时间
		uint32_t spd_now;	// Y 当前转速
		uint32_t cnt;		// X 计时值
	} nc_cc_sw_type;

#define C_ST_NC_STOP      0
#define C_ST_CC_RUN       1
#define C_ST_CC_STOP      2
#define C_ST_NC_RUN       3
	
	//顺序为 C_ST_NC_STOP->C_ST_CC_RUN->C_ST_CC_STOP->C_ST_NC_RUN, 某段时间设为0则跳过,STOP不可跳过，0时如果切换方向也要等待spdnow为0----
	//cct和nct同时为0时强制为start输出----
	uint8_t nc_cc_sw_handle(nc_cc_sw_type *obj, uint8_t en, uint8_t pulse);

	/*----加减速控制----*/
	typedef struct
	{
		uint32_t spd_now;
		uint32_t spd_set;
		uint32_t spd_out;
		uint32_t spd_up;
		uint32_t spd_dn;
		uint32_t spd_rl;
		uint8_t pwm_out_under_min; //输出小于下限值标记----
	} spd_inc_type;

	uint32_t  spd_inc_handle(spd_inc_type * obj, uint8_t pulse);



	typedef struct
	{
		uint8_t micro_req;	//输出次数请求。周期4，方波50%输出-
		uint8_t short_req;	//输出次数请求。周期8，方波50%输出-
		uint8_t mid_req;	//输出次数请求。周期16，方波50%输出-
		uint8_t long_req;	//输出次数请求。周期32，方波50%输出-
		uint8_t auto_req;	//自定义请求，次数
		uint8_t auto_period;  //自定义请求，周期
		uint8_t auto_duty;	//自定义请求，占空比
		uint8_t pulse_cnt;	//base bpulse
		uint8_t b_beep_st;	//输出状态-
	} beep_notice_type;

	void beep_handle(beep_notice_type *obj, uint8_t bpulse);
	void beep_clear(beep_notice_type *obj);
	void beep_auto_req(beep_notice_type *obj, uint8_t req_cnt, uint8_t period, uint8_t duty);
	void beep_micro_req(beep_notice_type *obj, uint8_t req_cnt);
	void beep_short_req(beep_notice_type *obj, uint8_t req_cnt);
	void beep_mid_req(beep_notice_type *obj, uint8_t req_cnt);
	void beep_long_req(beep_notice_type *obj, uint8_t req_cnt);

	/*-------------------------------------------------------------------------------------------------------------------------*/
	typedef struct
	{
		uint8_t run_st;			//Y
		uint8_t out;			//X
		int8_t dir;				//X -1下降，1上升，0未知
		uint8_t dir_keep_cnt;	//X
		uint8_t dir_keep_sv;	//Y

		int16_t sv;				//Y
		int16_t pv;				//Y
		int16_t en_offset;		//Y
		int16_t dis_offset;		//Y
		int16_t dir_zone;		//Y
		int16_t min;			//X
		int16_t max;			//X
	} comp_out_type;

	uint8_t comp_out_handle(comp_out_type *obj, uint8_t dir_adj_pulse);      //正作用
	uint8_t comp_out_nev_handle(comp_out_type *obj, uint8_t dir_adj_pulse);  //反作用

	typedef struct
	{
		// input
		uint8_t req;			// 执行请求
		uint8_t condition;		// 执行允许条件
		uint8_t st_back;		// 执行结果返回
		uint8_t exe_max;		// 执行失败最大次数
		uint16_t exe_time_sv;	// 执行时间设定值
		uint16_t idle_time_sv;	// 执行时间设定值

		// output
		uint16_t exe_time_cnt;	// 执行时间计时
		uint16_t idle_time_cnt;	// 执行时间计时
		uint8_t exe_st;			// 执行次数
		uint8_t err;			// 执行失败 //st_back有效自动清除。可外部清除，清除前无法重启
		uint8_t out;			// 输出状态
	} out_exe_type;

	void out_exe_hadle(out_exe_type * obj, uint8_t pulse);


#ifdef    __cplusplus
}
#endif

#endif    /* IO_HANDLE_H_ */

